/*
 * Powered By XY
 * Since 2020
 */

package com.xy.biz.uc.controller;

import com.xy.biz.uc.domain.bo.ResourceBO;
import com.xy.biz.uc.domain.converter.ResourceConverter;
import com.xy.biz.uc.domain.dto.ResourceDTO;
import com.xy.biz.uc.domain.query.ResourceQuery;
import com.xy.biz.uc.domain.req.GetResourceRequest;
import com.xy.biz.uc.domain.req.ListResourceRequest;
import com.xy.biz.uc.domain.req.ListResourceTreeItemRequest;
import com.xy.biz.uc.domain.req.SaveResourceRequest;
import com.xy.biz.uc.service.ResourceService;
import com.xy.lang.domain.Page;
import com.xy.lang.domain.Result;
import com.xy.lang.domain.treeing.Tree;
import com.xy.lang.domain.treeing.TreeItem;
import com.xy.lang.util.CollectionUtilsEx;
import com.xy.lang.validation.UpdateChecks;
import com.xy.lang.validation.annotation.Validatable;
import com.xy.tool.util.BeanUtilsEx;
import lombok.Builder;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import static com.xy.biz.uc.domain.bo.ResourceBO.STATUS_ENABLE;
import static com.xy.biz.uc.domain.bo.ResourceBO.TYPE_MENU;

/**
 * 
 * 
 * @author zsp
 * @date 2020-8-19
 */
@Slf4j
@RestController
@RequestMapping("/api/uc/resource")
public class ResourceController {

	@Autowired
	private ResourceService resourceService;
	
	@Validatable(groups = {UpdateChecks.class})
	@PostMapping(value = "/update")
	public Result<?> updateResource(@RequestBody SaveResourceRequest request) {
		resourceService.updateResource(ResourceConverter.toBO(request));
		return Result.success();
	}
	
	@Validatable
	@PostMapping(value = "/get")
	public Result<ResourceDTO> getResource(@RequestBody GetResourceRequest request) {
		return Result.success(ResourceConverter.toDTO(resourceService.getResource(request.getResourceId())));
	}

	@PostMapping(value = "/list_by_id")
	public Result<List<ResourceDTO>> listResourceById(@RequestBody Collection<Long> collection) {
		return Result.success(ResourceConverter.toDTO(resourceService.listResourceById(collection)));
	}

	@PostMapping(value = "/list")
	public Result<List<ResourceDTO>> listResource(@RequestBody ListResourceRequest request) {
		ResourceQuery query = ResourceConverter.toQuery(request);
		List<ResourceBO> resourceBOList = resourceService.listResource(query);
		return Result.success(toResourceDTO(query, resourceBOList));
	}

	@PostMapping(value = "/count")
	public Result<Integer> countResource(@RequestBody ListResourceRequest request) {
		return Result.success(resourceService.countResource(ResourceConverter.toQuery(request)));
	}

	@PostMapping(value = "/page")
	public Result<Page<ResourceDTO>> pageResource(@RequestBody ListResourceRequest request) {
		ResourceQuery query = ResourceConverter.toQuery(request);
		List<ResourceBO> resourceBOList = resourceService.listResource(query);
		List<ResourceDTO> resourceDTOList = toResourceDTO(query, resourceBOList);
		int count = resourceService.countResource(query);
		return Result.success(new Page<>(resourceDTOList, count));
	}

	private List<ResourceDTO> toResourceDTO(ResourceQuery query, List<ResourceBO> resourceBOList) {
		List<ResourceDTO> resourceDTOList = BeanUtilsEx.copyPropertiesForNewList(resourceBOList, () -> new ResourceDTO());
		if(query.getWithParentResource() != null && query.getWithParentResource().booleanValue()
				&& !CollectionUtils.isEmpty(resourceDTOList)) {
			CollectionUtilsEx.foreachSetParent(resourceDTOList,
					ResourceDTO::getResourceId,
					ResourceDTO::getParentResourceId,
					e -> BeanUtilsEx.copyPropertiesForNewList(
							resourceBOList.stream()
									.filter(ee -> ee.getParentResource() != null)
									.map(ResourceBO::getParentResource)
									.collect(Collectors.toSet()),
							() -> new ResourceDTO()),
					(resourceDTO, parentResourceDTO) -> resourceDTO.setParentResource(parentResourceDTO));
		}
		return resourceDTOList;
	}

	@Validatable
	@PostMapping(value = "list_tree_item_for_manage")
	public Result<List<TreeItem>> listResourceTreeItemForManage(@RequestBody ListResourceTreeItemRequest request) {
		List<ResourceBO> resourceBOList = resourceService.listResource(ResourceQuery.max()
				.applicationCode(request.getApplicationCode())
				.parentResourceId(request.getParentResourceId())
				.type(request.getType())
				.status(STATUS_ENABLE)
				.adminFlag(request.getAdminFlag())
				.build());
		if(!CollectionUtils.isEmpty(resourceBOList)) {
			return Result.success(Tree.buildTreeItem(resourceBOList,
					e -> e.getSource().getResourceId(),
					e -> e.getSource().getParentResourceId(),
					e -> e == null || e == 0,
					e -> e.getResourceId().toString(),
					e -> e.getName(),
					e -> ResourceTag.builder().module(e.getModule()).type(e.getType()).build()));
		}
		return Result.success(Collections.emptyList());
	}

	@Data
	@Builder
	static class ResourceTag {
		/**
		 * 模块
		 */
		private String module;
		/**
		 * 类型：1-菜单，2-功能
		 */
		private Integer type;
	}
	
}
